using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace Decav.Transactions
{
    /// <summary>
    /// Finds all public get/set properties of an object and returns them as
    /// binding targets.  Also finds "PropertyNameChanged" events and returns them
    /// as member changed events.
    /// </summary>
    [Serializable]
    public class PublicPropertyBoundPropertiesSelector : IBoundPropertiesSelector
    {
        #region IBindingTargetSelector Members

        public BindingTarget[] GetTargets(object obj)
        {
            if (obj == null)
                throw new ArgumentNullException("obj");

            Type objType = obj.GetType();

            List<BindingTarget> targets = new List<BindingTarget>();

            // Get the publically accessible properties and get them as targets
            foreach (PropertyInfo prop in objType.GetProperties(_publicPropConstant))
            {

                targets.Add(new BindingTarget(obj, prop, GetChangedEvent(objType, prop)));
            }

            return targets.ToArray();
        }

        #endregion

        internal static EventInfo GetChangedEvent(Type objType, PropertyInfo property)
        {
            string changedEventName = string.Format("{0}Changed", property.Name);
            return objType.GetEvent(changedEventName, BindingFlags.Public | BindingFlags.Instance);
        }

        internal static readonly BindingFlags _publicPropConstant = BindingFlags.GetProperty | BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.Instance;
    }
}
